﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

using IGolovkine.ShoutCastRipper.Service.Configuration;
using IGolovkine.ShoutCastRipper.Filters;
using IGolovkine.Core.Diagnostics;

namespace IGolovkine.ShoutCastRipper.Service
{
    public class StationRipperServiceHost : IDisposable
    {
        private ILogWriter _logger;
        private IDictionary<string, IStationRipperService> _instances;

        public StationRipperServiceHost(StationRipperServiceSection configSection)
        {
            Debug.NotDefault(() => configSection);
            _instances = new Dictionary<string, IStationRipperService>();
            _logger = this.CreateLogWriter(configSection);

            foreach (StationRipperElement configElement in configSection.RadioRecorders)
            {
                IStationRipperService service = this.CreateStationRecorderService(configElement);
                _instances.Add(service.Name, service);
                _logger.WriteLine("Created '{0}'", configElement);
                _logger.WriteLine();
            }

            foreach (StationRipperElement configElement in configSection.RadioRecorders) 
            {
                if (!string.IsNullOrEmpty(configElement.BackUpStationRecorder))
                {
                    if (_instances.ContainsKey(configElement.BackUpStationRecorder))
                    {
                        _instances[configElement.Name].AttachBackUp(_instances[configElement.BackUpStationRecorder]);
                    }
                    else
                    {
                        throw new ArgumentException(string.Format("Couldn't find back up instance '{0}'", configElement.BackUpStationRecorder));
                    }
                }
            }
        }

        protected virtual ILogWriter CreateLogWriter(StationRipperServiceSection p)
        {
            CompositeLogWriter logWriter = new CompositeLogWriter();
            logWriter.LogWriters.Add(new ConsoleLogWriter("System"));
            logWriter.LogWriters.Add(new FileLogWriter(p.LoggerParameter));
            return logWriter;
        }

        protected virtual IStationRipperService CreateStationRecorderService(StationRipperElement p)
        {
            return new StationRipperService(p);
        }

        public void StartAll()
        {
            try
            {
                foreach (IStationRipperService service in _instances.Values)
                {
                    if (service.Ripper.IsStarted == false)
                    {
                        service.Ripper.Start();
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.WriteException("Error starting all instances", ex);
                _logger.WriteLine();
                throw ex;
            }
        }

        public void Stop(string name)
        {
            try
            {
                _instances[name].Ripper.Stop();
            }
            catch (Exception ex)
            {
                _logger.WriteException("Error stopping instance", ex);
                _logger.WriteLine();
                throw ex;
            }
        }

        public void Start(string name)
        {
            try
            {
                _instances[name].Ripper.Start();
            }
            catch (Exception ex)
            {
                _logger.WriteLine("Error starting instance", ex);
                _logger.WriteLine();
                throw ex;
            }
        }

        public void StopAll()
        {
            try
            {
                foreach (IStationRipperService service in _instances.Values)
                {
                    if (service.Ripper.IsStarted)
                    {
                        service.Ripper.Stop();
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.WriteLine(ObjectDumper.Format(ex));
                _logger.WriteLine();
                throw ex;
            }
        }

        public void Dispose()
        {
            _instances.Values.ToList().ForEach(i => i.Dispose());
        }
    }
}
